# 导入FastAPI模块
from fastapi import FastAPI

# 创建app实例
from starlette.middleware.cors import CORSMiddleware

app = FastAPI(
    title='xxxx ',
    description='xxx',
    version='1.0.0'
)
app.add_middleware(
    CORSMiddleware,
    # 允许跨域的源列表，例如 ["http://www.example.org"] 等等，["*"] 表示允许任何源
    allow_origins=["*"],
    # 跨域请求是否支持 cookie，默认是 False，如果为 True，allow_origins 必须为具体的源，不可以是 ["*"]
    allow_credentials=False,
    # 允许跨域请求的 HTTP 方法列表，默认是 ["GET"]
    allow_methods=["*"],
    # 允许跨域请求的 HTTP 请求头列表，默认是 []，可以使用 ["*"] 表示允许所有的请求头
    # 当然 Accept、Accept-Language、Content-Language 以及 Content-Type 总之被允许的
    allow_headers=["*"],
    # 可以被浏览器访问的响应头, 默认是 []，一般很少指定
    expose_headers=["*"]
    # 设定浏览器缓存 CORS 响应的最长时间，单位是秒。默认为 600，一般也很少指定
    # max_age=1000
)

## 连接数据库

# 连接mysql数据库需要导入pymysql模块
import pymysql

pymysql.install_as_MySQLdb()

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 配置数据库地址：数据库类型+数据库驱动名称://用户名:密码@机器地址:端口号/数据库名
engine = create_engine("mysql+pymysql://root:123456@localhost:3306/MattersManage", encoding='utf-8')
# 把当前的引擎绑定给这个会话；
# autocommit：是否自动提交 autoflush：是否自动刷新并加载数据库 bind：绑定数据库引擎
Session = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 实例化
session = Session()

# declarative_base类维持了一个从类到表的关系，通常一个应用使用一个Base实例，所有实体类都应该继承此类对象
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

from sqlalchemy import Column, String, Integer, BigInteger, Boolean


# 创建数据库模型（定义表结构:表名称，字段名称以及字段类型）
class User(Base):
    # 定义表名
    __tablename__ = 'User'
    # 定义字段
    # primary_key=True 设置为主键
    userid = Column(Integer, primary_key=True)
    username = Column(String(255))
    password = Column(String(255))

    # 构造函数
    def __init__(self, userid, username, password):
        self.userid = userid
        self.username = username
        self.password = password

    # 打印形式
    def __str__(self):
        return "id：%s, name：%s，password：%s" % (str(self.userid), self.username, self.password)

    # 定义返回结果
    def to_dict(self):
        return {
            "userid": self.userid,
            "username": self.username,
            "password": self.password
        }


# 创建数据库模型（定义表结构:表名称，字段名称以及字段类型）
class Matter(Base):
    # 定义表名
    __tablename__ = 'Matter'
    # 定义字段
    # primary_key=True 设置为主键
    matterid = Column(Integer, primary_key=True)
    info = Column(String(255))
    date = Column(BigInteger)
    type = Column(String(255))
    important = Column(String(255))
    detail = Column(String(255))
    isfinish = Column(Boolean)

    # 构造函数
    def __init__(self, matterid, info, date, type, important, detail, isfinish):
        self.matterid = matterid
        self.info = info
        self.date = date
        self.type = type
        self.important = important
        self.detail = detail
        self.isfinish = isfinish

    # 定义返回结果
    def to_dict(self):
        return {
            "info": self.info,
            "date": self.date,
            "type": self.type,
            "important": self.important,
            "detail": self.detail,
            "isfinish": self.isfinish
        }


# 创建数据库模型（定义表结构:表名称，字段名称以及字段类型）
class Types(Base):
    # 定义表名
    __tablename__ = 'Types'
    # 定义字段
    # primary_key=True 设置为主键
    userid = Column(Integer, primary_key=True)
    username = Column(String(255))

    # 构造函数
    def __init__(self, userid, username):
        self.userid = userid
        self.username = username

    # 定义返回结果
    def to_dict(self):
        return {
            "userid": self.userid,
            "username": self.username,
        }


# 创建数据库模型（定义表结构:表名称，字段名称以及字段类型）
class Clock(Base):
    # 定义表名
    __tablename__ = 'Clock'
    # 定义字段
    # primary_key=True 设置为主键
    clockid = Column(Integer, primary_key=True)
    clocktype = Column(String(255))
    clocktime = Column(BigInteger)
    clockinfo = Column(String(255))

    # 构造函数
    def __init__(self, clockid, clocktype, clocktime, clockinfo):
        self.clockid = clockid
        self.clocktype = clocktype
        self.clocktime = clocktime
        self.clockinfo = clockinfo

    # 定义返回结果
    def to_dict(self):
        return {
            "clockid": self.clockid,
            "clocktype": self.clocktype,
            "clocktime": self.clocktime,
            "clockinfo": self.clockinfo
        }


# 在数据库中生成表
Base.metadata.create_all(bind=engine)

### 添加数据

from pydantic import BaseModel


#######################################################################################################
# 用户
# 定义数据模型
class CreatUser(BaseModel):
    userid: int
    username: str
    password: str

    def __str__(self):
        return "id：%s, name：%s, password：%s" % (str(self.userid), self.username, self.password)


## 添加单个
@app.post("/user/addUser")
async def InserUser(user: CreatUser):
    try:
        # 添加数据
        dataUser = User(userid=user.userid, username=user.username, password=user.password)
        session.add(dataUser)
        session.commit()
        session.close()
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}
    return {"code": "0000", "message": "添加成功"}


### 查询
@app.get("/user/{username}")
async def queryUserByUserId(username: str):
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        # one与first的区别：
        # one：要求结果集中只有一个结果；如果数据库返回0或2个或更多结果，并且将引发异常，则为错误。
        # first：返回可能更大的结果集中的第一个，如果没有结果，则返回None。不会引发异常。
        # filter_by与filter的区别：
        # filter_by接收的参数形式是关键字参数，而filter接收的参数是更加灵活的SQL表达式结构
        # user1 = session.query(User).filter_by(userid=user_id).first()
        user1 = session.query(User).filter(User.username == username).first()
        session.close()
        # 由于user1只有一个值，所以它直接是一个字典
        if user1:
            return {"code": "0000", "message": "请求成功", "data": user1}
        else:
            return {"code": "0001", "message": "查询无结果"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


## 查询所有
@app.get("/user/selectall/")
async def queryUserByUserId():
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        user1 = session.query(User).all()
        session.close()
        # user1 是一个列表，内部元素为字典
        return {"code": "0000", "message": "请求成功", "data": user1}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


###删除
# 根据user_id删除单个
@app.delete("/user/deleteUser/{user_id}")
async def deleteUser(user_id: int):
    try:
        user1 = session.query(User).filter(User.userid == user_id).first()
        if user1:
            session.delete(user1)
            session.commit()
            session.close()
            return {"code": "0000", "message": "删除成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


###修改
## 根据user_id修改user_name
@app.put("/user/updateUser/")
# 定义查询参数user_id和user_name
async def updateUser(user_id: int, user_name: str, pass_word: str):
    try:
        user1 = session.query(User).filter(User.userid == user_id).first()
        print(user1)
        if user1:
            user1.username = user_name
            user1.password = pass_word
            session.commit()
            session.close()
            return {"code": "0000", "message": "修改成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


#######################################################################################################
# 事项
# 定义数据模型
class CreatMatter(BaseModel):
    matterid: int
    info: str
    date: int
    type: str
    important: str
    detail: str
    isfinish: bool


## 添加单个
@app.post("/matter/addMatter")
async def InserMatter(matter: CreatMatter):
    try:
        # 添加数据
        dataMatter = Matter(matterid=0, info=matter.info, date=matter.date, type=matter.type,
                            important=matter.important, detail=matter.detail, isfinish=matter.isfinish)
        session.add(dataMatter)
        session.commit()
        session.close()
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}
    return {"code": "0000", "message": "添加成功"}


### 查询
@app.get("/matter/{matter_id}")
async def queryUserByMatterId(matterid: int):
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        # one与first的区别：
        # one：要求结果集中只有一个结果；如果数据库返回0或2个或更多结果，并且将引发异常，则为错误。
        # first：返回可能更大的结果集中的第一个，如果没有结果，则返回None。不会引发异常。
        # filter_by与filter的区别：
        # filter_by接收的参数形式是关键字参数，而filter接收的参数是更加灵活的SQL表达式结构
        # user1 = session.query(User).filter_by(userid=matterid).first()
        matter = session.query(Matter).filter(Matter.matterid == matterid).first()
        session.close()
        # 由于matter只有一个值，所以它直接是一个字典
        if matter:
            return {"code": "0000", "message": "请求成功", "data": matter}
        else:
            return {"code": "0001", "message": "查询无结果"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


## 查询所有
@app.get("/matter/selectall/")
async def queryMatterByUserId():
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        matters = session.query(Matter).all()
        session.close()
        # matters 是一个列表，内部元素为字典
        return {"code": "0000", "message": "请求成功", "data": matters}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


###删除
# 根据user_id删除单个
@app.delete("/matter/deleteMatter/")
async def deleteMatter(matterid: int):
    try:
        matter = session.query(Matter).filter(Matter.matterid == matterid).first()
        if matter:
            session.delete(matter)
            session.commit()
            session.close()
            return {"code": "0000", "message": "删除成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


###修改
## 根据user_id修改user_name
@app.put("/matter/updateMatter/")
# 定义查询参数user_id和user_name
async def updateMatter(matter_param: CreatMatter):
    try:
        print(matter_param)
        matter = session.query(Matter).filter(Matter.matterid == matter_param.matterid).first()
        if matter:
            matter.info = matter_param.info
            matter.date = matter_param.date
            matter.type = matter_param.type
            matter.important = matter_param.important
            matter.detail = matter_param.detail
            matter.isfinish = matter_param.isfinish

            session.commit()
            session.close()
            return {"code": "0000", "message": "修改成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


#######################################################################################################
# 分类
# 定义数据模型
class CreatTypes(BaseModel):
    userid: int
    username: str


## 添加单个
@app.post("/types/addtypes")
async def Insertypes(types: CreatTypes):
    try:
        # 添加数据
        dataUser = Types(userid=types.userid, username=types.username)
        session.add(dataUser)
        session.commit()
        session.close()
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}
    return {"code": "0000", "message": "添加成功"}


### 查询
@app.get("/types/{types_id}")
async def queryUserByUserId(user_id: int):
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        # one与first的区别：
        # one：要求结果集中只有一个结果；如果数据库返回0或2个或更多结果，并且将引发异常，则为错误。
        # first：返回可能更大的结果集中的第一个，如果没有结果，则返回None。不会引发异常。
        # filter_by与filter的区别：
        # filter_by接收的参数形式是关键字参数，而filter接收的参数是更加灵活的SQL表达式结构
        # user1 = session.query(User).filter_by(userid=user_id).first()
        user1 = session.query(Types).filter(Types.userid == user_id).first()
        session.close()
        # 由于user1只有一个值，所以它直接是一个字典
        if user1:
            return {"code": "0000", "message": "请求成功", "data": user1}
        else:
            return {"code": "0001", "message": "查询无结果"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


## 查询所有
@app.get("/types/selectall/")
async def querytypesByUserId():
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        user1 = session.query(Types).all()
        session.close()
        # user1 是一个列表，内部元素为字典
        return {"code": "0000", "message": "请求成功", "data": user1}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


###删除
# 根据user_id删除单个
@app.delete("/types/deletetypes/")
async def deleteUser(user_id: int):
    try:
        user1 = session.query(Types).filter(Types.userid == user_id).first()
        if user1:
            session.delete(user1)
            session.commit()
            session.close()
            return {"code": "0000", "message": "删除成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


###修改
## 根据user_id修改user_name
@app.put("/types/updateTypes/")
# 定义查询参数user_id和user_name
async def updateUser(type: CreatTypes):
    try:
        user1 = session.query(Types).filter(Types.userid == type.userid).first()
        print(user1)
        if user1:
            user1.username = type.username
            session.commit()
            session.close()
            return {"code": "0000", "message": "修改成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


#######################################################################################################
# 打卡
# 定义数据模型
class CreatClock(BaseModel):
    clockid: int
    clocktime: int
    clocktype: str
    clockinfo: str


## 添加单个
@app.post("/clock/addclock")
async def InserMatter(clock: CreatClock):
    try:
        # 添加数据
        dataMatter = Clock(clockid=0, clocktime=clock.clocktime, clocktype=clock.clocktype,
                           clockinfo=clock.clockinfo)
        session.add(dataMatter)
        session.commit()
        session.close()
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}
    return {"code": "0000", "message": "添加成功"}


### 查询
@app.get("/clock/{clock_id}")
async def queryclockByclockid(clockid: int):
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        # one与first的区别：
        # one：要求结果集中只有一个结果；如果数据库返回0或2个或更多结果，并且将引发异常，则为错误。
        # first：返回可能更大的结果集中的第一个，如果没有结果，则返回None。不会引发异常。
        # filter_by与filter的区别：
        # filter_by接收的参数形式是关键字参数，而filter接收的参数是更加灵活的SQL表达式结构
        # user1 = session.query(User).filter_by(userid=clockid).first()
        matter = session.query(Clock).filter(Clock.clockid == clockid).first()
        session.close()
        # 由于matter只有一个值，所以它直接是一个字典
        if matter:
            return {"code": "0000", "message": "请求成功", "data": matter}
        else:
            return {"code": "0001", "message": "查询无结果"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


## 查询所有
@app.get("/clock/selectall/")
async def queryclockByUserId():
    # 创建Query查询，filter是where条件，调用one返回唯一行，调用all则是返回所有行
    try:
        matters = session.query(Clock).all()
        session.close()
        # matters 是一个列表，内部元素为字典
        return {"code": "0000", "message": "请求成功", "data": matters}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库异常"}


###删除
# 根据user_id删除单个
@app.delete("/clock/deleteclock/")
async def deleteMatter(clockid: int):
    try:
        matter = session.query(Clock).filter(Clock.clockid == clockid).first()
        if matter:
            session.delete(matter)
            session.commit()
            session.close()
            return {"code": "0000", "message": "删除成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}


###修改
## 根据user_id修改user_name
@app.put("/clock/updateclock/")
# 定义查询参数user_id和user_name
async def updateclock(clock: CreatClock):
    try:
        matter = session.query(Clock).filter(Clock.clockid == clock.clockid).first()
        if matter:
            matter.clocktime = clock.clocktime
            matter.clocktime = clock.clocktime
            matter.clocktype = clock.clocktype
            matter.clockinfo = clock.clockinfo

            session.commit()
            session.close()
            return {"code": "0000", "message": "修改成功"}
        else:
            return {"code": "0001", "message": "参数错误"}
    except ArithmeticError:
        return {"code": "0002", "message": "数据库错误"}
